/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦，本文采用木兰宽松许可证第2版]
 * 
 * https://zhiqim.org/project/zhiqim_kit/zhiqim_git.htm
 *
 * ZhiqimGit is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.git.http;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.zhiqim.git.GitConstants;
import org.zhiqim.git.constants.GitOptionConstants;
import org.zhiqim.git.objer.objectid.ObjectId;
import org.zhiqim.git.util.GitStreams;

import org.zhiqim.kernel.util.Asserts;
import org.zhiqim.kernel.util.Strings;

/**
 * 上传包请求
 * clone格式如下：
 * want 88bb34f4af9f686c01e3a6a09dc06a1a538c7aac multi_ack_detailed side-band-64k thin-pack ofs-delta
 * want 88bb34f4af9f686c01e3a6a09dc06a1a538c7aac
 * want f717c4825b48b4f784e3eafb2fdfb852a6112aa3
 * done
 * 
 * fetch格式如下：
 * want c1a22ca1e7278eccd8f278c403aab4639e3e0e7b multi_ack_detailed no-done side-band-64k thin-pack ofs-delta agent=git/2.6.0.windows.1
 * have f14d1ab9294ffc098918a2ca4874810f8a85b8d3
 * have 85ad3d741ae2b25d4befb4453227e6075d005a94
 * have 746874e27761e660fac3ad5c7d6278b0e21c166a
 * have a049b79afcfaca7088802633a09a720efb6b5391
 * have 211ebca8d7dede7c7bc7104fa110c9bdd6dc12e9
 * have 4f9339bc408ab42367ef00470fcd0de0e4bf2e74
 * have e5f523a6f61781c7c6855b667db562fb251a4398
 * done 
 * 
 * @version v1.0.0 @author zouzhigang 2016-12-2 新建与整理
 */
public class UploadRequest implements GitConstants, GitOptionConstants
{
    private List<ObjectId> wantIds = new ArrayList<>();
    private Set<String> options = new HashSet<>();
    private List<ObjectId> haveIds = new ArrayList<>();
    private boolean hasDoneEnd = false;
    
    /**
     * 解析请求，包括want&have&done
     * 
     * @param input         输入流
     * @throws IOException  IO异常
     */
    public UploadRequest parse(InputStream input) throws IOException
    {
        boolean isFirst = true;
        while (true)
        {//读取want，clone时有多个,fetch时只有一个
            String line = GitStreams.readString(input);
            if (line == null)
                break;
            
            if (!line.startsWith("want ") || line.length() < 45)
                throw Asserts.exception("上传包错误，不是[want]格式：" + line);

            if (isFirst && line.length() > 45)
            {//首行把参数读出来
                String opts = Strings.trim(line.substring(45));
                for (String opt : opts.split(" "))
                    options.add(opt);
                
                line = line.substring(0, 45);
                isFirst = false;
            }

            wantIds.add(ObjectId.parse(line.substring(5)));
        }
        
        while (true)
        {//读取have和done
            String line = GitStreams.readString(input);
            if (line == null)
            {//未读到done即结束，hasDoneEnd = false;
                break;
            }
            
            if (line.equals("done"))
            {//done
                hasDoneEnd = true;
                break;
            }
            
            if (line.startsWith("have ") && line.length() == 45)
            {//have 4f9339bc408ab42367ef00470fcd0de0e4bf2e74
                haveIds.add(ObjectId.parse(line.substring(5)));
            }
        }
        
        return this;
    }
    
    /****************************************************************/
    //获取方法
    /****************************************************************/

    public List<ObjectId> getWantList()
    {
        return wantIds;
    }
    
    public Set<String> getOptionList()
    {
        return options;
    }
    
    public List<ObjectId> getHaveList()
    {
        return haveIds;
    }
    
    /****************************************************************/
    //业务方法
    /****************************************************************/
    
    public boolean hasDoneEnd()
    {
        return hasDoneEnd;
    }
    
    public boolean hasWant()
    {
        return !wantIds.isEmpty();
    }
    
    public ObjectId getFirstWant()
    {
        return wantIds.get(0);
    }
    
    public boolean hasHave()
    {
        return !haveIds.isEmpty();
    }
    
    public boolean hasOption(String option)
    {
        return options.contains(option);
    }
    
    public boolean hasSideBand()
    {
        return options.contains(OPTION_SIDE_BAND) || options.contains(OPTION_SIDE_BAND_64K);
    }
    
    public boolean isSideBand()
    {
        return options.contains(OPTION_SIDE_BAND);
    }
    
    public boolean isSideBand64k()
    {
        return options.contains(OPTION_SIDE_BAND_64K);
    }
    
    public boolean isMultAck()
    {
        return options.contains(OPTION_MULTI_ACK);
    }
    
    public boolean isMultAckDetailed()
    {
        return options.contains(OPTION_MULTI_ACK_DETAILED);
    }
    
    public boolean hasMultAck()
    {
        return options.contains(OPTION_MULTI_ACK) || options.contains(OPTION_MULTI_ACK_DETAILED);
    }
    
    public boolean isNoDone()
    {
        return options.contains(OPTION_NO_DONE);
    }
    
    public boolean isNoProgress()
    {
        return options.contains(OPTION_NO_PROGRESS);
    }
}
